﻿'***************************************************************************\
' Module Name: AudioEndpointTabControl.vb
' Project: SetDefaultAudioEndpoint http://sdae.codeplex.com/
' Copyright 2011 by jeff
' 
' This source is subject to the GNU General Public License version 2 (GPLv2).
' See http://www.gnu.org/licenses/gpl-2.0.html.
' All other rights reserved.
' 
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
' EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
' WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
'***************************************************************************/

Imports System.Windows.Automation

Namespace Windows7

  Class AudioEndpointTabControl

    'The Windows Sound window tab controls for "Playback" and "Recording" are of interest.
    'Those items are abstracted to the audio endpoint tabs.
    'Each audio endpoint tab has two items of interest:
    ' the list control of audio endpoints; and the "Set Default" button.
    'The audio endpoint tab has the capabilities to:
    '  * return a list of audio endpoints
    '  * set the default audio endpoint by list index number
    'To return a list of audio endpoints, we must ask the list control to 

    Private ReadOnly myAudioEndpointTab As AutomationElement

    Public Sub New(ByVal tab As AutomationElement)
      If (tab Is Nothing) Then
        Throw New ArgumentNullException("tab")
      End If

      Me.myAudioEndpointTab = tab
    End Sub

    Public Sub SetDefaultAudioEndpoint(ByVal endpoint As IAudioEndpoint)
      If (endpoint Is Nothing) Then
        Throw New ArgumentNullException("endpoint")
      End If

      'select our tab; brings its device list into view
      Me.SelectElement()

      'select audio device
      endpoint.SelectElement()

      'throw exception if we can't set audio device as default
      If (Not Me.CanSetAudioDeviceAsDefault) Then
        Throw New WindowsSoundException(String.Format(Globalization.CultureInfo.CurrentCulture, "The audio device '{0}' could not be set as the default audio device. It is either not enabled, or is already the default audio device.", endpoint.Name))
      End If

      'click on Set Default button
      Me.ClickSetDefaultButtonControl()
    End Sub

    Private Function CanSetAudioDeviceAsDefault() As Boolean
      'we can set currently-selected audio device as default
      ' if the Set Default button is enabled
      Return Me.SetDefaultButtonControl.Current.IsEnabled
    End Function

    Private Sub ClickSetDefaultButtonControl()
      Me.SetDefaultButtonControl.ClickElement()
    End Sub

    Private Sub SelectElement()
      Me.TabControl.SelectElement()
    End Sub

    Private ReadOnly Property TabControl() As AutomationElement
      Get
        Return Me.myAudioEndpointTab
      End Get
    End Property

    Private Function SetDefaultButtonControl() As AutomationElement
      Const SetDefaultButtonAutomationId As String = "1002"

      Dim result As AutomationElement = Me.TabControl.FindFirstInChildrenByAutomationId(SetDefaultButtonAutomationId)

      If (result Is Nothing) Then
        Throw New ElementNotAvailableException("Could not find Set Default button on Sound control panel window.")
      End If

      Return result
    End Function

    Private Function AudioEndpointListControl() As AudioEndpointListControl
      'the audio device list is the control that shows each audio endpoint

      Const AudioEndpointListAutomationId As String = "1000"

      Dim result As AutomationElement = Me.TabControl.FindFirstInChildrenByAutomationId(AudioEndpointListAutomationId)

      If (result Is Nothing) Then
        Throw New ElementNotAvailableException("Could not find audio device list control on Sound control panel window.")
      End If

      Return New AudioEndpointListControl(result)
    End Function

    Public ReadOnly Property Endpoints() As IAudioEndpointList
      Get
        'a side-effect to this function: the correct tab must be visible in order to query its endpoints
        Me.SelectElement()

        'get endpoints from the list control
        Return Me.AudioEndpointListControl.Endpoints
      End Get
    End Property
  End Class

End Namespace